package com.demo.security.access.impl;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;

import com.demo.security.access.AccessLogicInvocation;
import com.demo.security.access.AccessLogicManager;
import com.demo.security.access.LogicAttribute;
import com.demo.security.core.SecurityMessageSource;

/**
 * 抽象访问逻辑管理器 处理访问逻辑代理提供的各种前置逻辑处理
 * 
 * @author ryuu.kk
 */
public abstract class AbstractAccessLogicManager<T> implements AccessLogicManager, InitializingBean, MessageSourceAware {

	/**
	 * Log日志
	 */
	protected final Log logger = LogFactory.getLog(getClass());

	private List<AccessLogicInvocation<T>> logicInvocations;

	protected MessageSourceAccessor messages = SecurityMessageSource.getAccessor();

	public AbstractAccessLogicManager(List<AccessLogicInvocation<T>> logicInvocations) {
		Assert.notEmpty(logicInvocations, "A list of AccessDecisionVoters is required");
		this.logicInvocations = logicInvocations;
	}

	public void afterPropertiesSet() throws Exception {
		Assert.notEmpty(this.logicInvocations, "A list of AccessLogicInvocation is required");
		Assert.notNull(this.messages, "A message source must be set");
	}

	public List<AccessLogicInvocation<T>> getLogicInvocations() {
		return this.logicInvocations;
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messages = new MessageSourceAccessor(messageSource);
	}

	/**
	 * 逻辑调用管理是否支持配置属性
	 * @param attribute 配置属性
	 * @return 是否支持
	 */
	public boolean supports(LogicAttribute attribute) {
		if (logicInvocations != null) {
			for (AccessLogicInvocation<T> invoker : this.logicInvocations) {
				if (invoker.supports(attribute)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 逻辑调用管理是否支持对象类
	 * @param clazz 目标对象
	 * @return 是否支持
	 */
	public boolean supports(Class<?> clazz) {
		if (logicInvocations != null) {
			for (AccessLogicInvocation<T> invoker : this.logicInvocations) {
				if (invoker.supports(clazz)) {
					return true;
				}
			}
		}
		return false;
	}
}
